package com.xingkeduo.business.order.domain;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xingkeduo.business.order.remote.*;
import com.xingkeduo.business.order.remote.feign.AdminFeignService;
import com.xingkeduo.business.order.remote.feign.MarketingFeignService;
import com.xingkeduo.business.order.remote.feign.PaymentFeignService;
import com.xingkeduo.business.order.remote.feign.WordPadFeignService;
import com.xingkeduo.business.order.service.IdGenerateService;
import com.xingkeduo.business.order.service.OrderService;
import com.xingkeduo.config.DomainConfig;
import com.xingkeduo.delayQueue.model.TaskModel;
import com.xingkeduo.delayQueue.model.TaskModelEnum;
import com.xingkeduo.delayQueue.service.TaskService;
import com.xingkeduo.dto.*;
import com.xingkeduo.dto.enums.ConsumNoticeEnums;
import com.xingkeduo.dto.enums.StockStatusEnum;
import com.xingkeduo.dto.param.*;
import com.xingkeduo.dto.payment.*;
import com.xingkeduo.dto.response.OrderAdminResponseDto;
import com.xingkeduo.dto.response.OrderPayStatusDto;
import com.xingkeduo.dto.response.RefreshCodeResponseDto;
import com.xingkeduo.pojo.enums.*;
import com.xingkeduo.pojo.query.OrderDetailMapper;
import com.xingkeduo.pojo.query.OrderMapper;
import com.xingkeduo.pojo.query.OrderStatusLogMapper;
import com.xingkeduo.pojo.table.Order;
import com.xingkeduo.pojo.table.OrderDetail;
import com.xingkeduo.pojo.table.OrderStatusLog;
import com.xingkeduo.util.pojo.exception.BusinessException;
import com.xingkeduo.utils.DateTimeUtils;
import com.xingkeduo.utils.ResponseUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.xingkeduo.dto.WebsocketMessageResponse.MessageTypeEnum.ANNOUNCE_NUMBER;
import static com.xingkeduo.dto.payment.ChannelType.WECHAT_JSAPI;
import static com.xingkeduo.dto.payment.ChannelType.WECHAT_MINA;
import static com.xingkeduo.pojo.enums.OrderSource.PAY_FOR_ANOTHER;
import static com.xingkeduo.pojo.enums.OrderSource.SUI_XING_FU;
import static com.xingkeduo.utils.DateTimeUtils.*;

/**
 * @author chi  2019-02-19 16:34
 **/
@Service
@Slf4j
@Transactional
public class OrderDomainService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private OrderStatusLogMapper orderStatusLogMapper;

    @Resource
    private OrderService orderService;

    @Resource
    private TaskService taskService;

    @Resource
    private PaymentRemoteService paymentRemoteService;

    @Resource
    private StoreRemoteService storeRemoteService;
    @Resource
    private UserRemoteService userRemoteService;
    @Resource
    private InventoryRemoteService inventoryRemoteService;
    @Resource
    private IdGenerateService idGenerateService;
    @Resource
    private WaitLineRemoteService waitLineRemoteService;
    @Resource
    private AdminRemoteService adminRemoteService;
    @Resource
    private MarketingRemoteService marketingRemoteService;
    @Resource
    private MarketingFeignService marketingFeignService;
    @Resource
    private WordPadFeignService wordPadFeignService;
    @Resource
    private AdminFeignService adminFeignService;
    @Resource
    private MessagePushService messagePushService;
    @Resource
    private PaymentFeignService paymentFeignService;

    @Resource
    private Environment environment;
    @Resource
    private DomainConfig domainConfig;

    private ExecutorService executorService = Executors.newSingleThreadExecutor();

    /**
     * 生成待支付的订单
     *
     * @return
     */
    public String initOrder(OrderInitDto orderInitDto) {
        getUserOrderState(orderInitDto.getUserId());
        //未服务完成的订单判断
        serviceNotRendered(orderInitDto);
        Order order = new Order();
        OrderDetail orderDetail = new OrderDetail();

        //门店详情
        StoreRemoteDto storeRemoteDto = storeRemoteService.queryStore(orderInitDto.getStoreId(), orderInitDto.getServiceTypeId());
        if (storeRemoteDto != null) {
            BeanUtils.copyProperties(storeRemoteDto, order);
            order.setAllPrice(storeRemoteDto.getStorePrice());

        }

        //获取发型师配置价格
        CraftsmanServiceTO craftsmanServiceTO = adminRemoteService.listCraftsmanPriceByShopIdAndServiceId(Long.valueOf(orderInitDto.getStoreId()), Long.valueOf(orderInitDto.getServiceTypeId()), Long.valueOf(orderInitDto.getAppointmentAdminId()));
        if (craftsmanServiceTO != null) {
            order.setAllPrice(craftsmanServiceTO.getPrices());
        }

        // 用户详情
        UserRemoteDto userRemoteDto = userRemoteService.getByUserId(orderInitDto.getUserId()).orElseThrow(() -> new BusinessException(BusinessException.Type.DEFAULT, "用户不存在"));
        BeanUtils.copyProperties(userRemoteDto, order);

        order.setUserId(orderInitDto.getUserId())
                .setStoreId(orderInitDto.getStoreId())
                .setAppointmentAdminId(orderInitDto.getAppointmentAdminId())
                .setAppointmentAdminName(orderInitDto.getAppointmentAdminName())
                .setAdminId(orderInitDto.getAppointmentAdminId())
                .setAdminName(orderInitDto.getAppointmentAdminName())
                .setAppointmentStartTime(DateTimeUtils.yyyy_MM_dd_H_m_s(orderInitDto.getAppointmentStartTime()))
                .setAppointmentEndTime(DateTimeUtils.yyyy_MM_dd_H_m_s(orderInitDto.getAppointmentEndTime()))
                .setServiceTypeId(orderInitDto.getServiceTypeId())
                .setOrderSource(orderInitDto.getOrderSource())
                .setServiceTypeName(storeRemoteService.getServprod(order.getServiceTypeId()))
                .setAppointmentId(orderInitDto.getAppointmentId())
                .setServiceDown(false);

        //获取最优活动信息
        MarketActivityDto marketActivityInfo = marketingRemoteService.getMarketActivityInfo(order);
        optimal(order, marketActivityInfo, "1");


        order.init(idGenerateService.get(),domainConfig.isRelease());

        String orderLabels = orderService.getLabels(order.getUserId(), order.getAppointmentAdminId());
        order.setLabels(orderLabels);
        order.setDesignatedCustomer(orderLabels.contains("指定客"));

        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.NOT_PAY, OrderAction.订单创建);

        orderMapper.insert(order);

        //锁定库存
        boolean b = inventoryRemoteService.lockInventory(order.getAppointmentId(), StockStatusEnum.WAIT_FOR_PAYMENT, order);
        if (!b) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "锁定库存失败");
        }

        orderStatusLog.setOrderId(order.getId());
        orderStatusLogMapper.insert(orderStatusLog);

        orderDetail.setOrderNo(order.getOrderNo());
        orderDetail.setActivityDetail(order.getActivityDetail());
        orderDetail.setCardCouponDetail(order.getCardCouponDetail());
        orderDetailMapper.insert(orderDetail);

        //添加60秒倒计时关闭订单
        taskService.addToDeplayQueue(new TaskModel(String.valueOf(order.getId()), TaskModelEnum.close_order));
        return order.getOrderNo();
    }


    /**
     * 获取最优活动信息
     *
     * @param order
     */
    public void optimal(Order order, MarketActivityDto marketActivityInfo, String status) {
        log.info("optimal marketActivityInfo:{}", JSON.toJSONString(marketActivityInfo));
//        MarketActivityDto marketActivityInfo = marketingRemoteService.getMarketActivityInfo(order);
        //判断是否有活动
        order.setFreeCard(false);
        order.setActivityPrice(BigDecimal.ZERO);
        //没有选择优惠券先置空
        order.setActivityType("");
        order.setActivityDetail("");
        order.setActivityId("");


        if (marketActivityInfo != null && marketActivityInfo.getActivityType() != null) {
            Integer activityType = marketActivityInfo.getActivityType();
            Integer activityDiscountType = marketActivityInfo.getActivityDiscountType();
            BigDecimal activityPrice = marketActivityInfo.getActivityDenominationAmount();
            switch (activityDiscountType) {//优惠方式 0 立减，1 折扣，2 特价
                case 0:
                    //如果立减价格小于原价，优惠价格为立减价格，否则优惠价为原价
                    order.setActivityPrice(order.getAllPrice().compareTo(activityPrice) == 1 ? activityPrice : order.getAllPrice());
                    break;
                case 1:
                    //总价*折扣 折扣不能大于1
                    activityPrice = BigDecimal.ONE.compareTo(activityPrice) == 1 ? activityPrice : BigDecimal.ONE;
                    order.setActivityPrice(order.getAllPrice().multiply((BigDecimal.ONE.subtract(activityPrice))));
                    break;
                case 2:
                    // 总价格-特价
                    order.setActivityPrice(order.getAllPrice().compareTo(activityPrice) == 1 ? order.getAllPrice().subtract(activityPrice) : BigDecimal.ZERO);
                    break;
            }
            ActivityDto activityDto = new ActivityDto();
            BeanUtils.copyProperties(marketActivityInfo, activityDto);
            order.setActivityType(String.valueOf(activityType));
            order.setActivityDetail(JSON.toJSONString(activityDto));
            order.setActivityId(String.valueOf(marketActivityInfo.getActivityId()));
        }


        order.setMarketingPrice(BigDecimal.ZERO);
        order.setSubsidiesPrice(BigDecimal.ZERO);
        //没有选择卡券先设置为空
        order.setMarketingType("");
        order.setCardCouponDetail("");
        order.setMarketingId("");
        order.setFreeCard(false);


        //总价-活动价之后的价格
        BigDecimal countPrice = order.getAllPrice().subtract(order.getActivityPrice());
        log.info("optimal countPrice:{}", countPrice);
        if (countPrice.compareTo(BigDecimal.ZERO) == 1 && marketActivityInfo != null && marketActivityInfo.getMarketingType() != null) {
            //判断是否有卡券
            Integer marketingType = marketActivityInfo.getMarketingType();
            Integer marketingDenomination = marketActivityInfo.getMarketingDiscountType();
            BigDecimal marketPrice = marketActivityInfo.getMarketingDenominationAmount();
            log.info("optimal marketPrice:{}", marketPrice);
            switch (marketingDenomination) {//优惠方式 0 立减，1 折扣，2 特价
                case 0:
                    order.setMarketingPrice(countPrice.compareTo(marketPrice) == 1 ? marketPrice : countPrice);
                    break;
                case 1:
                    //折扣不能大于100%
                    marketPrice = BigDecimal.ONE.compareTo(marketPrice) == 1 ? marketPrice : BigDecimal.ONE;
                    order.setMarketingPrice(countPrice.compareTo(countPrice.multiply(BigDecimal.ONE.subtract(marketPrice))) == 1 ? countPrice.multiply(BigDecimal.ONE.subtract(marketPrice)) : countPrice);
                    break;
                case 2:
                    order.setMarketingPrice(countPrice.compareTo(marketPrice) == 1 ? countPrice.subtract(marketPrice) : BigDecimal.ZERO);
                    break;
                case 3:
                    order.setMarketingPrice(countPrice.compareTo(marketPrice) == 1 ? countPrice.subtract(marketPrice) : BigDecimal.ZERO);
                    break;
            }
            MarketDto marketDto = new MarketDto();
            BeanUtils.copyProperties(marketActivityInfo, marketDto);
            order.setMarketingType(String.valueOf(marketingType));
            order.setCardCouponDetail(JSON.toJSONString(marketDto));
            order.setMarketingId(String.valueOf(marketActivityInfo.getMarketingId()));


            if (marketingDenomination == 3 && marketActivityInfo.getMarketingType() == 2) {
                order.setFreeCard(true);
            }
        }

        //如果优惠活动信息不为空，则默认优活动

        order.setOptimal(status);

        //总价-优惠=支付
        order.setCouponPrice(order.getActivityPrice().add(order.getMarketingPrice()));
        BigDecimal payPrice = order.getAllPrice().compareTo(order.getCouponPrice()) == 1 ? order.getAllPrice().subtract(order.getCouponPrice()) : BigDecimal.ZERO;
        order.setPayPrice(payPrice);

        if (marketActivityInfo != null && marketActivityInfo.getMarketingType() != null) {
            //计算公司补贴金额
            BigDecimal platformSubsidyAmount = getPlatformSubsidyAmount(order.getAllPrice(), order.getPayPrice(), order.getMarketingPrice(), marketActivityInfo.getMarketingSubsidyType(), marketActivityInfo.getMarketingSubsidyBasicAmount());
            log.info("optimal 公司补贴金额:{}", platformSubsidyAmount);
            order.setSubsidiesPrice(platformSubsidyAmount);
        }
    }


    /**
     * 获取发型师金额
     *
     * @param storeId
     * @param serviceTypeId
     * @return
     */
    public Map<String, PriceDto> allPrice(String adminIds, String storeId, String serviceTypeId) {
        log.info("获取发型师金额allPrice adminIds:{}", adminIds);

        if (StringUtils.isBlank(adminIds)) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "发型师不能为空");
        }

        BigDecimal price = BigDecimal.ZERO;
        //门店详情
        StoreRemoteDto storeRemoteDto = storeRemoteService.queryStore(storeId, serviceTypeId);
        if (storeRemoteDto != null) {
            price = storeRemoteDto.getStorePrice();
        }
        log.info("{}门店价格:{}", storeId, price);

        String[] split = adminIds.split(",");

        Map<String, PriceDto> map = Arrays.stream(split).map(PriceDto::new).collect(Collectors.toMap(PriceDto::getAdminId, p -> p));

        //获取发型师配置价格
        for (String adminId : split) {
            CraftsmanServiceTO craftsmanServiceTO = adminRemoteService.listCraftsmanPriceByShopIdAndServiceId(Long.valueOf(storeId), Long.valueOf(serviceTypeId), Long.valueOf(adminId));
            log.info("craftsmanServiceTO:{}", JSON.toJSONString(craftsmanServiceTO));
            BigDecimal adminPrice = price;
            if (craftsmanServiceTO != null) {
                adminPrice = craftsmanServiceTO.getPrices();
            }
            log.info("{}发型师价格:{}", adminId, adminPrice);
            map.get(adminId).setCurrPrice(adminPrice);
        }


        ResponseUtils<List<ActivityApiResponseVo>> batchHairdresserActivity = null;
        try {
            log.info("getBatchHairdresserActivity: storeId:{}, hairStyleIds:{}", storeId, Arrays.stream(split).collect(Collectors.joining(",")));
            batchHairdresserActivity = marketingFeignService.getBatchHairdresserActivity(Long.valueOf(storeId), Arrays.stream(split).collect(Collectors.joining(",")));
            log.info("batchHairdresserActivity response :{}", JSON.toJSONString(batchHairdresserActivity));
            if (batchHairdresserActivity.success()) {
                List<ActivityApiResponseVo> data = batchHairdresserActivity.getData();
                for (String adminId : split) {
                    BigDecimal currprice = map.get(adminId).getCurrPrice();
                    ;
                    data.stream().filter(activityApiResponseVo -> activityApiResponseVo.getHairStyleId().longValue() == Long.valueOf(adminId).longValue())
                            .findFirst().ifPresent(a -> {
                        map.get(adminId).setReducePrice(currprice.subtract(a.getActivityAmount()).doubleValue() <= 0 ? currprice : a.getActivityAmount())
                                .setActivityId(a.getId() + "")
                                .setActivityContent(a.getSubTitle())
                                .setActivityName(a.getName())
                                .setActivityType(a.getActivityType());
                    });
                }
            }
        } catch (Exception e) {
            log.error("远程调用活动出错:{}", e);
        }
        return map;
    }


    /**
     * 新建随信付订单
     *
     * @param orderInitDto
     * @return
     */
    public Map<Object, Object> suixinPay(SuixinPayInitDto orderInitDto) {
        Order order = new Order();

        if (orderInitDto.getAllPrice().doubleValue() <= 0) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "请输入正确金额");
        }


        //门店详情
        StoreRemoteDto storeRemoteDto = storeRemoteService.queryStore(orderInitDto.getStoreId(), null);
        if (storeRemoteDto != null) {
            BeanUtils.copyProperties(storeRemoteDto, order);
        }

        order.setStoreId(orderInitDto.getStoreId())
                .setAdminId(orderInitDto.getAppointmentAdminId())
                .setAdminName(orderInitDto.getAppointmentAdminName())
                .setAllPrice(orderInitDto.getAllPrice())
                .setPayPrice(orderInitDto.getAllPrice())
                .setGatheringType(orderInitDto.getGatheringType())
                .setRemark(orderInitDto.getRemark())
                .setOrderSource(SUI_XING_FU)
                .setServiceDown(true);

        order.init(idGenerateService.get(),domainConfig.isRelease());
        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.NOT_PAY, OrderAction.随星付订单创建);

        orderMapper.insert(order);
        orderStatusLog.setOrderId(order.getId());
        orderStatusLogMapper.insert(orderStatusLog);

        taskService.addToDeplayQueue(new TaskModel(String.valueOf(order.getId()), TaskModelEnum.close_suixingfu_order));

        Map<Object, Object> map = new HashMap<>();
        map.put("orderId", order.getId());
        return map;
    }


    /**
     * 代购
     *
     * @return
     */
    public ResponseUtils payForAnother(PayForAnotherInitDto orderInitDto, String ip) {
        Order order = new Order();
        OrderDetail orderDetail = new OrderDetail();

        //门店详情
        StoreRemoteDto storeRemoteDto = storeRemoteService.getByStoreId(orderInitDto.getStoreId());
        if (storeRemoteDto != null) {
            BeanUtils.copyProperties(storeRemoteDto, order);
        }

        // 用户id不传,其他写死
        CraftsmanDTO admin = adminRemoteService.getAdmin(orderInitDto.getAppointmentAdminId());
        if (admin != null) {
            order.setUserNickName(admin.getNickName());
            order.setUserMobile(admin.getPhone());
            order.setUserHeadUrl(admin.getPath());
        }

        order.setStoreId(orderInitDto.getStoreId())
                .setAppointmentAdminId(orderInitDto.getAppointmentAdminId() + "")
                .setAppointmentAdminName(orderInitDto.getAppointmentAdminName())
                .setAllPrice(orderInitDto.getAllPrice())
                .setPayPrice(orderInitDto.getAllPrice())
                .setOrderSource(OrderSource.PAY_FOR_ANOTHER)
                .setPayForAnotherTypeId(orderInitDto.getPayForAnotherTypeId())
                .setPayForAnotherTypeName(orderInitDto.getPayForAnotherTypeName())
                .setServiceTypeName("单人剪发服务")
                .setServiceDown(false);
        //.setAppointmentId(appointmentId);
        order.init(idGenerateService.get(), domainConfig.isRelease());


        //取消之前做的代付订单
        List<Order> orderList = orderMapper.selectList(new QueryWrapper<Order>()
                .lambda().eq(Order::getStatus, OrderStatus.NOT_PAY)
                .eq(Order::getAppointmentAdminId, orderInitDto.getAppointmentAdminId())
                .eq(Order::getOrderSource, PAY_FOR_ANOTHER));

        if (orderList != null && orderList.size() > 0) {
            for (Order order1 : orderList) {
                closeOrder(order1.getId() + "");
            }
        }


        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.NOT_PAY, OrderAction.发型师代付);
        orderMapper.insert(order);

        //锁定库存
        StockParam stockParam = StockParam.builder()
                .lineNo(order.getWaitingLineNo())
                .orderNo(order.getOrderNo())
                .storeId(Long.valueOf(order.getStoreId()))
                .staffId(Long.valueOf(order.getAppointmentAdminId()))
                .status(StockStatusEnum.WAIT_FOR_PAYMENT.getValue())
                .userPath(order.getUserHeadUrl())
                .build();
        ResponseUtils<StockForOrderVo> stockForOrderVoResponseUtils = null;
        try {
            stockForOrderVoResponseUtils = wordPadFeignService.lockMinFreeStock(stockParam);
        } catch (Exception e) {
            log.error("代付锁定库存失败:{}", e);
            throw new BusinessException(BusinessException.Type.DEFAULT, "锁定库存失败");
        }
        log.info("lockMinFreeStock response{}", stockForOrderVoResponseUtils);
        if (!stockForOrderVoResponseUtils.success() || stockForOrderVoResponseUtils.getData() == null) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "今日无库存无法代购,请使用随星付支付");
        }
        StockForOrderVo data = stockForOrderVoResponseUtils.getData();
        order.setAppointmentId(data.getStockId() + "");

        LocalDateTime startTime = LocalTime.parse(data.getStartTime(), HH_mm_ss).atDate(LocalDate.now());
        LocalDateTime endTime = LocalTime.parse(data.getEndTime(), HH_mm_ss).atDate(LocalDate.now());
        order.setAppointmentStartTime(startTime);
        order.setAppointmentEndTime(endTime);

        orderMapper.updateById(order);


        orderStatusLog.setOrderId(order.getId());
        orderStatusLogMapper.insert(orderStatusLog);

        orderDetail.setOrderNo(order.getOrderNo());
        orderDetail.setActivityDetail(order.getActivityDetail());
        orderDetail.setCardCouponDetail(order.getCardCouponDetail());
        orderDetailMapper.insert(orderDetail);


        if (order.getPayPrice().compareTo(BigDecimal.ZERO) == 0) {
            //0元自动支付成功
            log.info("{}零元支付", order.getOrderNo());
            PayeeOrderResponseDto payeeOrderResponseDto = PayeeOrderResponseDto.builder()
                    .outTradeNo(order.getOrderNo())
                    .amount(BigDecimal.ZERO)
                    .payTime(LocalDateTime.now())
                    .payType(ThirdpartyType.WECHAT)
                    .payeeOrderStatus(PayeeOrderStatus.SUCCESS)
                    .build();

            paid(payeeOrderResponseDto);
            return ResponseUtils.getSuccess();
        }


        //调起微信支付
        PayeeWechatJSAPIParam payeeOrderParam = new PayeeWechatJSAPIParam();
        payeeOrderParam.setAmount(order.getPayPrice());
        payeeOrderParam.setAttach(order.getId() + "");
        payeeOrderParam.setStoreId(order.getStoreId());
        payeeOrderParam.setMerchantId("1");
        payeeOrderParam.setNotifyUrl("");
        payeeOrderParam.setOutTradeNo(order.getOrderNo());
        payeeOrderParam.setPayType(ThirdpartyType.WECHAT);
        payeeOrderParam.setProductName("星客多 (" + order.getStoreName() + ")");
        payeeOrderParam.setProductMessage(orderInitDto.getPayForAnotherTypeName());
        payeeOrderParam.setClientIp(ip);
        payeeOrderParam.setTradeType(TradeType.APP);
        ResponseUtils responseUtils = paymentRemoteService.toPay(payeeOrderParam);

        //添加60秒倒计时关闭订单
        taskService.addToDeplayQueue(new TaskModel(String.valueOf(order.getId()), TaskModelEnum.close_order));

        return responseUtils;
    }


    /**
     * 取消订单
     *
     * @param id
     * @return
     */
    public boolean cancel(String id) {
        log.info("order cancle :{}", id);
        Order order = orderService.getOrderById(id);
        return cancelOrder(order);
    }


    /**
     * 取消订单
     *
     * @param userId
     * @param orderNo
     * @return
     */
    public boolean cancelOrder(String userId, String orderNo) {
        Order order = orderService.getOrderByIdNo(userId, orderNo);
        return cancelOrder(order);
    }

    public boolean cancelOrder(Order order) {
        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.CANCEL, OrderAction.用户取消);
        //库存
        inventoryRemoteService.unlockInventory(order);
        orderMapper.updateById(order);
        orderStatusLogMapper.insert(orderStatusLog);
        return true;
    }

    /**
     * 支付成功
     *
     * @return
     */
    public boolean paid(PayeeOrderResponseDto payeeOrderResponseDto) {
        String outTradeNo = payeeOrderResponseDto.getOutTradeNo();
        Order order = orderService.queryOrderByOrderNO(outTradeNo);



        if (order.getPaySuccess()) {
            log.info("已支付");
            return true;
        }

        if(OrderStatus.CLOSE.equals(order.getStatus())){
            log.info("尝试锁定一次库存:{}", order.getOrderNo());
            inventoryRemoteService.lockInventory(order.getAppointmentId(), StockStatusEnum.WAIT_FOR_SERVICE, order);
        }



        OrderStatusLog orderStatusLog;
        if (SUI_XING_FU.equals(order.getOrderSource())) {
            //直接变成已服务
            orderStatusLog = order.covertStatus(OrderStatus.EVALUATION_DONE, OrderAction.支付成功);

            order.setServeStartTime(LocalDateTime.now());
            order.setServeEndTime(LocalDateTime.now());
            order.setServiceDown(true);
            //随行付  不需要 排队号
            order.paid(payeeOrderResponseDto, null, idGenerateService.get());


            ThirdpartyType payType = payeeOrderResponseDto.getPayType();
            JSONObject jsonObject = new JSONObject();
            if (ThirdpartyType.WECHAT.equals(payType)) {
                String openId = payeeOrderResponseDto.getOpenId();
                jsonObject.put("openid", openId);
            } else {
                String sellerId = payeeOrderResponseDto.getSellerId();
                jsonObject.put("login", sellerId);
            }

            ResponseUtils<WxMaUserInfo> consumerInfo = adminFeignService.getConsumerInfo(JSON.toJSONString(jsonObject));
            log.info("{}获取用户信息返回:{}", jsonObject, JSON.toJSONString(consumerInfo));
            if (consumerInfo.success()) {
                WxMaUserInfo data = consumerInfo.getData();
                order.setUserId(data.getId());
                order.setUserMobile(data.getPhone());
                order.setUserNickName(data.getNickName());
            }

        } else if (PAY_FOR_ANOTHER.equals(order.getOrderSource())) {
            orderStatusLog = order.covertStatus(OrderStatus.PAID, OrderAction.支付成功);
            order.paid(payeeOrderResponseDto, waitLineRemoteService.getWaitLineNo(String.valueOf(order.getStoreId()), order.getAppointmentStartTime()), idGenerateService.get());

            inventoryRemoteService.updateInventory(StockStatusEnum.WAIT_FOR_SERVICE, order);

        } else {
            orderStatusLog = order.covertStatus(OrderStatus.PAID, OrderAction.支付成功);
            order.paid(payeeOrderResponseDto, waitLineRemoteService.getWaitLineNo(String.valueOf(order.getStoreId()), order.getAppointmentStartTime()), idGenerateService.get());
            //通知库存
            inventoryRemoteService.updateInventory(StockStatusEnum.WAIT_FOR_SERVICE, order);

        }

        if(PayType.WECHAT.equals(order.getPayType())){
            order.setOutOrderNo(payeeOrderResponseDto.getTradeNo());
        }else if(PayType.ALIPAY.equals(order.getPayType())){
            order.setAlipayTradeNo(payeeOrderResponseDto.getTradeNo());
        }


        orderMapper.updateById(order);
        orderStatusLogMapper.insert(orderStatusLog);
        log.info("下单成功修改用户券，order{}", order);
        marketingRemoteService.placeOrder(order);

        try {
            //补全店铺，发型师名称信息
            orderService.complementInfo(order);
            //订单支付成功通知
            messagePushService.pushPaySuccessMessage(order);
            //服务进度提醒
            sendPush(order);
        } catch (Exception e) {
            log.error("支付后通知出错:{}", e);
        }
        bindBarberReceiveAccount(order);


        try {
            StatisticsServiceDto build = StatisticsServiceDto.builder()
                    .id(order.getUserId())
                    .consumNotice(ConsumNoticeEnums.PAY_SUCCESS)
                    .payTime(order.getPayTime())
                    .orderNo(order.getOrderNo())
                    .build();

            String marketingType = order.getMarketingType();
            String insert = adminFeignService.insert(build);
            log.info("StatisticsServiceDto: {}, {}", JSON.toJSONString(build), insert);
        } catch (Exception e) {
            log.error("StatisticsServiceDto error: {}", e);
        }

        return true;
    }

    /**
     * 关闭订单,由延时队列调用,勿删
     *
     * @param id
     */
    public void closeOrder(String id) {
        log.info("closeOrder id=" + id);
        Order orderById = orderService.getOrderById(id);

        if (orderById.getStatus().equals(OrderStatus.CLOSE)) {
            return;
        }


        if (!orderById.getStatus().equals(OrderStatus.NOT_PAY)) {
            log.info("{}未能取消订单{}", orderById.getId(), orderById.getStatus());
            return;
        }

        ResponseUtils<PayeeOrderResponseDto> query = paymentFeignService.query("1", orderById.getOrderNo());
        if (query.success()) {
            PayeeOrderResponseDto data = query.getData();
            PayeeOrderStatus payeeOrderStatus = data.getPayeeOrderStatus();
            if (PayeeOrderStatus.SUCCESS.equals(payeeOrderStatus)) {
                log.info("{}未能取消订单,已支付成功", orderById.getId(), orderById.getStatus());
                return;
            }
        }

        OrderStatusLog orderStatusLog = orderById.covertStatus(OrderStatus.CLOSE, OrderAction.订单关闭);
        orderMapper.updateById(orderById);

        //库存
        inventoryRemoteService.unlockInventory(orderById);

        orderStatusLogMapper.insert(orderStatusLog);
    }

    /**
     * 发型师开始服务
     *
     * @return
     */
    public boolean inService(OrderInserviceDto orderInserviceDto) {

        /**
         * 发型师点击服务校验：
         * 1.常规校验：登陆app是否有效（如果无效强退app），排班考勤是否有效（无效则强制下班）
         * 2.正在服务校验：一个发型师同时只能服务一个订单，如果有另一个订单在服务，则弹窗提示（原型2.5.5）
         * 3.叫号校验，一个订单是否有叫过号，如果没叫，提示先叫号在服务。
         */

        Integer integer = orderMapper.selectCount(new QueryWrapper<Order>().lambda()
                .eq(Order::getAdminId, orderInserviceDto.getAdminId())
                .eq(Order::getStatus, OrderStatus.IN_SERVICE));

        if (integer != null && integer > 0) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "您有订单正在服务中");
        }

        String id = orderInserviceDto.getId();
        String adminId = orderInserviceDto.getAdminId();
        String adminName = orderInserviceDto.getAdminName();
        log.info("inService Order id={},adminId={},adminName:{}", id, adminId, adminName);
        Order order = orderService.getOrderById(id);

        if (!orderInserviceDto.isFromTicketCode()) {

            Boolean freeCard = order.getFreeCard();
            if (freeCard != null && freeCard) {
                if (!order.getTicketCode().equals(orderInserviceDto.getTicketCode())) {
                    throw new BusinessException(BusinessException.Type.DEFAULT, "验票码不正确");
                }

                if (LocalDateTime.now().compareTo(order.getTicketCodeExpireTime()) > 0) {
                    throw new BusinessException(BusinessException.Type.DEFAULT, "验票码已过期,请联系顾客刷新后再试");
                }
            }
            OrderDetail orderDetail = orderDetailMapper.selectOne(new QueryWrapper<OrderDetail>().lambda().eq(OrderDetail::getOrderNo, order.getOrderNo()).last("LIMIT 1"));
            List<LocalDateTime> localDateTimes = orderDetail.announceCountlist();
            if (localDateTimes == null || localDateTimes.size() == 0) {
                throw new BusinessException(BusinessException.Type.DEFAULT, "请先叫号再服务");
            }

        }

        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.IN_SERVICE, OrderAction.开始服务);
        order.setAdminId(adminId);
        order.setAdminName(adminName);
        order.setServeStartTime(LocalDateTime.now());
        orderMapper.updateById(order);
        orderStatusLogMapper.insert(orderStatusLog);

        inventoryRemoteService.updateInventory(StockStatusEnum.IN_SERVICE, order);


        StatisticsServiceDto build = StatisticsServiceDto.builder()
                .id(order.getUserId())
                .serviceMoney(order.getPayPrice())
                .lastTime(order.getServeStartTime())
                .consumNotice(ConsumNoticeEnums.CONSUME_START)
                .orderNo(order.getOrderNo())
                .build();

        String marketingType = order.getMarketingType();
        if("1".equals(marketingType)){
            build.setCouponId(order.getMarketingId());
        }

        String insert = adminFeignService.insert(build);
        log.info("StatisticsServiceDto: {}, {}", JSON.toJSONString(build), insert);

        return true;
    }

    /**
     * 发型师完成服务
     *
     * @param id
     * @return
     */
    public boolean endService(String id) {
        Order order = orderService.getOrderById(id);

        if (order.getServiceDown() != null && order.getServiceDown()) {
            return false;
        }

        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.EVALUATION_DONE, OrderAction.结束服务);
        order.setServeEndTime(LocalDateTime.now());
        order.setServiceDown(true);

        orderStatusLogMapper.insert(orderStatusLog);

        LocalDateTime appointmentStartTime = order.getAppointmentStartTime();

        if (LocalDateTime.now().compareTo(appointmentStartTime) < 0) {
            inventoryRemoteService.unlockInventory(order);
            order.setAppointmentId(null);
        } else {
            inventoryRemoteService.updateInventory(StockStatusEnum.ALREADY, order);
        }
        //订单评价提醒
        int i = orderMapper.updateById(order);

        if (i == 0) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "完成失败,请重试");
        }

        messagePushService.pushServiceEvaluationMessage(order);
        orderService.completeSuccessMessage(order);
        return true;
    }

    @Resource
    private RabbitTemplate rabbitTemplate;

    /**
     * 叫号
     *
     * @param id
     * @return
     */
    public long announceNumber(String id) {
        Order order = orderService.getOrderById(id);

        if (!order.getStatus().equals(OrderStatus.PAID)) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "当前状态不能叫号");
        }


        OrderDetail orderDetail = orderDetailMapper.selectOne(new QueryWrapper<OrderDetail>().lambda().eq(OrderDetail::getOrderNo, order.getOrderNo()).last("LIMIT 1"));


        //发型师第一次叫号，如果叫号时间晚于预约时间20分钟，发送优惠券
        List<LocalDateTime> localTimes = orderDetail.announceCountlist();
        log.info("叫号,localTimes:{}", JSON.toJSONString(localTimes));
        if (localTimes.isEmpty()) {
            //获取当前时间
            LocalDateTime nowTime = LocalDateTime.now();
            LocalDateTime endTime = order.getAppointmentStartTime().plusMinutes(20);
            log.info("叫号 announceNumber  nowTime={},endTime={},adminName:{}", nowTime, endTime);
            if (nowTime.isAfter(endTime)) {
                log.info("发送优惠券，发送消");
                //     发送优惠券，发送消息
                bindReceiveAccount(order);

            }
        }

        orderDetail.announceNumber();
        orderMapper.updateById(order);
        orderDetailMapper.updateById(orderDetail);

        //调用电视屏幕

        OrderAnnounceMessageDto orderAnnounceMessageDto = new OrderAnnounceMessageDto();
        BeanUtils.copyProperties(order, orderAnnounceMessageDto);
        orderAnnounceMessageDto.setAppointmentAdminName(order.getAppointmentAdminNickName());
        orderAnnounceMessageDto.setStartTime(order.getAppointmentStartTime().toLocalTime().format(HH_mm));

        //rabbitMqSender.sendMessage("websocket_transfer_exchange", "websocket_transfer_key", JSON.toJSONString(new WebsocketMessageResponse<>(ANNOUNCE_NUMBER, order.getStoreId(), orderAnnounceMessageDto)));


        this.rabbitTemplate.convertAndSend("websocket_transfer_exchange", "websocket_transfer_key", JSON.toJSONString(new WebsocketMessageResponse<>(ANNOUNCE_NUMBER, order.getStoreId(), orderAnnounceMessageDto)), new CorrelationData(UUID.randomUUID().toString()));


        List<LocalDateTime> localDateTimes = orderDetail.announceCountlist();
        long count = localDateTimes.stream().filter(localDateTime -> localDateTime.compareTo(order.getAppointmentStartTime()) > 0).count();
        return count;
    }


    /**
     * 过号
     *
     * @return
     */
    public boolean overNumber(String id, boolean bf) {
        Order order = orderService.getOrderById(id);
        OrderDetail orderDetail = orderDetailMapper.selectOne(new QueryWrapper<OrderDetail>().lambda().eq(OrderDetail::getOrderNo, order.getOrderNo()).last("LIMIT 1"));

        if (LocalDateTime.now().compareTo(order.getAppointmentStartTime()) < 0) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "未到预约时间,不能过号");
        }

        if (bf) {

            List<LocalDateTime> localDateTimes = orderDetail.announceCountlist();

            long count = localDateTimes.stream().filter(localDateTime -> {
                return localDateTime.compareTo(order.getAppointmentStartTime()) > 0;
            }).count();

            if (count < 3) {
                throw new BusinessException(BusinessException.Type.DEFAULT, "未叫号3次,不能过号");
            }
        }


        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.OVER_NUMBER, OrderAction.订单过号);

        inventoryRemoteService.updateInventory(StockStatusEnum.OVERDUE, order);

        //允许重新修改时间
        order.setModifyOnce(false);

        orderMapper.updateById(order);
        orderStatusLogMapper.insert(orderStatusLog);
        //排队过号提醒
        messagePushService.pushQueueNumberMessage(order);
        return true;
    }

    /**
     * 过号重新预约
     *
     * @return
     */
    public boolean reApply(OrderAppointmentDto orderAppointmentDto) {
        Order order = orderService.queryOrderByOrderNO(orderAppointmentDto.getOrderNo());

        if (!order.getStatus().equals(OrderStatus.OVER_NUMBER)) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "状态异常");
        }
        log.info("过号重新预约orderAppointmentDto:{}", orderAppointmentDto);
        order.setAppointmentStartTime(DateTimeUtils.yyyy_MM_dd_H_m_s(orderAppointmentDto.getAppointmentStartTime()))
                .setAppointmentEndTime(DateTimeUtils.yyyy_MM_dd_H_m_s(orderAppointmentDto.getAppointmentEndTime()))
                .setAppointmentId(orderAppointmentDto.getAppointmentId());
        boolean bf = marketingRemoteService.getStoreBypassFlowActivityDetail(order);
        log.info("过号重新预约，修改预约时间:{}", bf);
        if (!bf) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "活动或价格不一致");
        }


        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.PAID, OrderAction.用户重新预约);
        //重新生成排队号
        String waitLineNo = waitLineRemoteService.getWaitLineNo(String.valueOf(order.getStoreId()), order.getAppointmentStartTime());
        if (StringUtils.isNotBlank(waitLineNo)) {
            order.setWaitingLineNo("A" + waitLineNo);
        }

        boolean b = inventoryRemoteService.lockInventory(orderAppointmentDto.getAppointmentId(), StockStatusEnum.WAIT_FOR_SERVICE, order);
        if (!b) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "锁定库存失败");
        }
        log.info("过号重新预约 order:{}", JSON.toJSONString(order));
        log.info("过号重新预约 orderStatusLog:{}", JSON.toJSONString(orderStatusLog));

        order.setModifyOnce(true);

        orderMapper.updateById(order);
        orderStatusLogMapper.insert(orderStatusLog);
        //预约变更提醒
        messagePushService.pushAppointmentChangeMessage(order);
        return true;
    }


    /**
     * 后台根据id修改订单信息 修改订单信息
     *
     * @param orderModifyDto
     */
    public boolean modify(OrderModifyDto orderModifyDto) {
        Order order = orderService.getOrderById(orderModifyDto.getId());
        String date = orderModifyDto.getDate();
        String startTime = orderModifyDto.getStartTime();
        String endTime = orderModifyDto.getEndTime();
        String adminId = orderModifyDto.getAdminId();
        startTime = date + " " + startTime + ":00";
        endTime = date + " " + endTime + ":00";

        LocalDateTime start = DateTimeUtils.yyyy_MM_dd_H_m_s(startTime);
        LocalDateTime end = DateTimeUtils.yyyy_MM_dd_H_m_s(endTime);

        if (start.compareTo(end) > 0) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "开始时间不能大于结束时间");
        }


        order.setAdminId(adminId);
        order.setServeStartTime(start);
        order.setServeEndTime(end);

        orderMapper.updateById(order);


        OrderStatusLog orderStatusLog = order.addOrderAction(OrderAction.后台修改订单信息);

        StringBuffer sb = new StringBuffer();
        sb.append(order.getStatus().getValue()+"_");
        sb.append(startTime+"-");
        sb.append(endTime);
        orderStatusLog.setRemark(sb.toString());

        orderStatusLogMapper.insert(orderStatusLog);
        return true;
    }

    /**
     * 后台根据id 完成订单
     *
     * @param orderModifyDto
     */
    public boolean complete(OrderModifyDto orderModifyDto) {
        Order order = orderService.getOrderById(orderModifyDto.getId());

        if (order.getServiceDown() != null && order.getServiceDown()) {
            return false;
        }


        String date = orderModifyDto.getDate();
        String startTime = orderModifyDto.getStartTime();
        String endTime = orderModifyDto.getEndTime();
        String adminId = orderModifyDto.getAdminId();

        startTime = date + " " + startTime + ":00";
        endTime = date + " " + endTime + ":00";

        order.setAdminId(adminId);
        order.setServeStartTime(DateTimeUtils.yyyy_MM_dd_H_m_s(startTime));
        order.setServeEndTime(DateTimeUtils.yyyy_MM_dd_H_m_s(endTime));
        order.setServiceDown(true);
        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.EVALUATION_DONE, OrderAction.后台完成服务);

        LocalDateTime appointmentStartTime = order.getAppointmentStartTime();

        if (LocalDateTime.now().compareTo(appointmentStartTime) < 0) {
            inventoryRemoteService.unlockInventory(order);
            order.setAppointmentId(null);
        } else {
            inventoryRemoteService.updateInventory(StockStatusEnum.ALREADY, order);
        }

        int i = orderMapper.updateById(order);

        if (i == 0) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "完成失败,请重试");
        }

        StringBuffer sb = new StringBuffer();
        sb.append(order.getStatus().getValue()+"_");
        sb.append(startTime+"-");
        sb.append(endTime);
        orderStatusLog.setRemark(sb.toString());

        orderStatusLogMapper.insert(orderStatusLog);
        orderService.completeSuccessMessage(order);
        return true;
    }


    public void test(String id) {
        log.info("================test id=" + id);
    }


    /**
     * 更改预约时间(支付前
     *
     * @param orderAppointmentDto
     */
    public void editAppointment(OrderAppointmentDto orderAppointmentDto) {
        Order order = orderService.queryOrderByOrderNO(orderAppointmentDto.getOrderNo());

        if (!OrderStatus.NOT_PAY.equals(order.getStatus())) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "订单状态已经改变");
        }
        if (order.getModifyOnce()) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "订单已更改过时间");
        }
        log.info("支付前过号重新预约orderAppointmentDto:{}", orderAppointmentDto);
        order.setAppointmentStartTime(DateTimeUtils.yyyy_MM_dd_H_m_s(orderAppointmentDto.getAppointmentStartTime()))
                .setAppointmentEndTime(DateTimeUtils.yyyy_MM_dd_H_m_s(orderAppointmentDto.getAppointmentEndTime()));
        //获取最优活动信息
        MarketActivityDto marketActivityInfo = marketingRemoteService.getMarketActivityInfo(order);
        log.info("marketActivityInfo query:{}", JSON.toJSONString(marketActivityInfo));
        optimal(order, marketActivityInfo, "1");

        //TODO chi 库存
        /*inventoryRemoteService.unlockInventory(order);
        inventoryRemoteService.lockInventory(orderAppointmentDto.getAppointmentId(), StockStatusEnum.WAIT_FOR_SERVICE, order);*/
        boolean b = inventoryRemoteService.changeInventory(orderAppointmentDto.getAppointmentId(), StockStatusEnum.WAIT_FOR_SERVICE, order);
        if(!b){
            throw new BusinessException(BusinessException.Type.DEFAULT, "改约失败");
        }


        order.setAppointmentId(orderAppointmentDto.getAppointmentId());
        if (!order.getStatus().equals(OrderStatus.NOT_PAY)) {
            order.setModifyOnce(true);
        }

        orderMapper.updateById(order);
        updateOrderDetail(order);
    }


    /**
     * 修改发型师id
     *
     * @param orderHairDto
     */
    public boolean editHair(OrderHairDto orderHairDto) {
        Order order = orderService.getOrderById(orderHairDto.getId());
        order.setHairId(Integer.valueOf(orderHairDto.getHairId()));
        orderMapper.updateById(order);
        return true;
    }

    /**
     * 修改发型师id
     *
     * @param orderHairDto
     */
    public boolean editHairByNo(OrderHairDto orderHairDto) {
        Order order = queryOrder(orderHairDto.getId());
        order.setHairId(Integer.valueOf(orderHairDto.getHairId()));
        orderMapper.updateById(order);
        return true;
    }

    /**
     * 发型师验票
     */
    public OrderAdminResponseDto checkTicket(String ticketCode, String storeId) {

        Order order = orderMapper.selectOne(new QueryWrapper<Order>().lambda().eq(Order::getTicketCode, ticketCode).eq(Order::getStoreId, storeId).in(Order::getStatus, new OrderStatus[]{OrderStatus.PAID, OrderStatus.OVER_NUMBER}));
        if (order == null) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "该订单不存在");
        }

        if (LocalDateTime.now().compareTo(order.getTicketCodeExpireTime()) > 0) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "验票码已过期,请联系顾客刷新后再试");
        }

        orderService.supplementOrder(order);

        OrderAdminResponseDto orderResponseDto = orderService.covertToOrderAdminResponseDto(order);
        return orderResponseDto;
    }


    /**
     * 获取验票码
     *
     * @param
     * @return
     */
    public RefreshCodeResponseDto obtainTicketNo(String orderNo) {
        Order order = queryOrder(orderNo);
        //过期更新验票码
        if (order.getFreeCard() != null && order.getFreeCard()) {
            order.initTicketcode(idGenerateService.get());
            orderMapper.updateById(order);
        }
        RefreshCodeResponseDto refreshCodeResponseDto = new RefreshCodeResponseDto();
        BeanUtils.copyProperties(order, refreshCodeResponseDto);
        refreshCodeResponseDto.setQrcodeUrl(qrcodeUrl(order.getTicketCode(), order.getStoreId()));
        return refreshCodeResponseDto;
    }

    /**
     * 生成验证码url
     *
     * @param ticketCode
     * @param storeId
     * @return
     */
    public String qrcodeUrl(String ticketCode, String storeId) {
        return environment.getProperty("doamin.gateway.url", String.class, "http://gateway.xingkeduo.com") + "/mobile/qrcode?data_url=" + ticketCode;
    }


    /**
     * 根据订单号 获取订单信息
     *
     * @param orderNo
     * @return
     */
    public Order queryOrder(String orderNo) {
        Order order = orderMapper.selectOne(new QueryWrapper<Order>().lambda().eq(Order::getOrderNo, orderNo).last("LIMIT 1"));
        if (order == null) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "订单不存在");
        }
        orderService.supplementOrder(order);
        return order;
    }


//    @PostConstruct
//    public void init() {
//        List<Order> orders = orderMapper.selectList(new QueryWrapper<Order>().lambda().eq(Order::getStatus, OrderStatus.NOT_PAY));
//        if (orders == null || orders.size() == 0) {
//            return;
//        }
//
//        for (Order order : orders) {
//
//            Duration between = Duration.between(order.getCreatedTime(), LocalDateTime.now());
//            long seconds = between.getSeconds();
//            if (seconds > 60) {
//                this.cancel(String.valueOf(order.getId()));
//            }
//        }
//    }


    /**
     * 查看订单是否为已支付
     *
     * @param id
     * @return 1, 支付成功
     * 0,支付失败
     * 2,支付中
     */
    public OrderPayStatusDto paidStatus(String id) {
        Order orderById = orderService.getOrderById(id);
        OrderPayStatusDto orderPayStatusDto = new OrderPayStatusDto();

        int payStatus = 2;
        if (orderById.getPaySuccess()) {
            payStatus = 1;

            orderPayStatusDto.setPayTime(orderById.getPayTime());
            orderPayStatusDto.setUserNickName(orderById.getUserNickName() + "");
            orderPayStatusDto.setPayPrice(orderById.getPayPrice());
            orderPayStatusDto.setPayTypeName(orderById.getPayTypeName());

        } else if (OrderStatus.CLOSE.equals(orderById.getStatus())) {
            payStatus = 0;
        }

        orderPayStatusDto.setPayStatus(payStatus);
        orderPayStatusDto.setOrderId(id);
        return orderPayStatusDto;
    }


    /**
     * 判断用户是否有未支付订单
     *
     * @param userId
     * @return
     */
    private void getUserOrderState(String userId) {
        // 获取账号合并ids
        String[] strings = adminRemoteService.queryUserIds(userId);
        Order order = orderMapper.selectOne(new QueryWrapper<Order>().lambda().in(Order::getUserId, strings).eq(Order::getStatus, OrderStatus.NOT_PAY).last("LIMIT 1"));
        if (order != null) {
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime createdTime = order.getCreatedTime().plusSeconds(60);
            if (now.isBefore(createdTime)) {
                BusinessException exception = new BusinessException(BusinessException.Type.DEFAULT, "你还有未支付订单");
                exception.setCode(order.getOrderNo());
                throw exception;
            }

        }
    }

    /**
     * 调用支付接口
     *
     * @param paymentParam
     * @return
     */
    public ResponseUtils toPay(PaymentParam paymentParam, String ip) {
        log.info("调用支付服务:{}", JSON.toJSONString(paymentParam));

        if (StringUtils.isBlank(paymentParam.getId()) && StringUtils.isBlank(paymentParam.getOrderNo())) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "订单id和订单号必传其一");
        }

        Order order;
        if (StringUtils.isNotBlank(paymentParam.getOrderNo())) {
            order = orderService.queryOrderByOrderNO(paymentParam.getOrderNo());
        } else {
            order = orderMapper.selectById(paymentParam.getId());
        }

        if (order == null) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "订单不存在");
        }
        orderService.supplementOrder(order);
        if (!OrderStatus.NOT_PAY.equals(order.getStatus())) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "订单" + order.getStatus().getValue());
        }

        //校验库存
        if(StringUtils.isNotBlank(order.getAppointmentId())){
            ResponseUtils<Boolean> stockIsEnable = wordPadFeignService.getStockIsEnable(Long.valueOf(order.getStoreId()), order.getOrderNo());
            log.info("校验库存:{}", stockIsEnable);
            if(stockIsEnable.success()){
                Boolean data = stockIsEnable.getData();
                if(data==null || !data){
                    throw new BusinessException(BusinessException.Type.DEFAULT, "请重新选择库存");
                }
            }else {
                throw new BusinessException(BusinessException.Type.DEFAULT, "请重新选择库存");
            }
        }


        if (order.getPayPrice().compareTo(BigDecimal.ZERO) == 0) {
            //0元自动支付成功
            log.info("{}零元支付", order.getOrderNo());
            ChannelType channelType = paymentParam.getChannelType();

            ThirdpartyType payType;
            if (ChannelType.ALIPAY.equals(channelType)) {
                payType = ThirdpartyType.ALIPAY;
            } else {
                payType = ThirdpartyType.WECHAT;
            }

            PayeeOrderResponseDto payeeOrderResponseDto = PayeeOrderResponseDto.builder()
                    .outTradeNo(order.getOrderNo())
                    .amount(BigDecimal.ZERO)
                    .payTime(LocalDateTime.now())
                    .payType(payType)
                    .payeeOrderStatus(PayeeOrderStatus.SUCCESS)
                    .build();

            paid(payeeOrderResponseDto);
            return ResponseUtils.getSuccess();
        }


        PayeeOrderParam payeeOrderParam;
        if (ChannelType.ALIPAY.equals(paymentParam.getChannelType())) {
            PayeeAlipayJSAPIParam payeeAlipayJSAPIParam = new PayeeAlipayJSAPIParam();

            if (StringUtils.isBlank(paymentParam.getBuyerId())) {
                UserRemoteDto remoteDto = userRemoteService.getByUserId(order.getUserId()).orElseThrow(() -> new BusinessException(BusinessException.Type.DEFAULT, "用户不存在"));
                payeeAlipayJSAPIParam.setBuyerId(remoteDto.getAliUserId());
            } else {
                payeeAlipayJSAPIParam.setBuyerId(paymentParam.getBuyerId());
            }

            StoreRemoteDto byStoreId = storeRemoteService.getByStoreId(order.getStoreId());
            if(byStoreId!=null && StringUtils.isNotBlank(byStoreId.getAlipayStoreId())){
                payeeAlipayJSAPIParam.setAlipayStoreId(byStoreId.getAlipayStoreId());
            }

            payeeAlipayJSAPIParam.setPayType(ThirdpartyType.ALIPAY);
            payeeAlipayJSAPIParam.setTradeType(TradeType.JSAPI);

            payeeOrderParam = payeeAlipayJSAPIParam;
        } else {
            //调起微信支付宝支付
            PayeeWechatJSAPIParam payeeWechatJSAPIParam = new PayeeWechatJSAPIParam();
            payeeWechatJSAPIParam.setPayType(ThirdpartyType.WECHAT);
            payeeWechatJSAPIParam.setClientIp(ip);


            if (StringUtils.isBlank(paymentParam.getOpenId())) {
                UserRemoteDto remoteDto = userRemoteService.getByUserId(order.getUserId()).orElseThrow(() -> new BusinessException(BusinessException.Type.DEFAULT, "用户不存在"));
                if (WECHAT_MINA.equals(paymentParam.getChannelType())) {

                    if(StringUtils.isBlank(remoteDto.getMinaOpenId())){
                        throw new BusinessException(BusinessException.Type.DEFAULT, "9004");
                    }
                    payeeWechatJSAPIParam.setOpenId(remoteDto.getMinaOpenId());
                } else if (WECHAT_JSAPI.equals(paymentParam.getChannelType())) {

                    if(StringUtils.isBlank(remoteDto.getGzhOpenId())){
                        throw new BusinessException(BusinessException.Type.DEFAULT, "9004");
                    }

                    payeeWechatJSAPIParam.setOpenId(remoteDto.getGzhOpenId());
                }
            } else {
                payeeWechatJSAPIParam.setOpenId(paymentParam.getOpenId());
            }


            switch (paymentParam.getChannelType()) {
                case WECHAT_APP: {
                    payeeWechatJSAPIParam.setTradeType(TradeType.APP);
                    break;
                }
                case WECHAT_MINA: {
                    payeeWechatJSAPIParam.setTradeType(TradeType.MINA);
                    break;
                }
                case WECHAT_JSAPI: {
                    payeeWechatJSAPIParam.setTradeType(TradeType.JSAPI);
                    break;
                }
            }
            payeeOrderParam = payeeWechatJSAPIParam;
        }


        LocalDateTime createdTime = order.getCreatedTime();
        long seconds = Duration.between(createdTime, LocalDateTime.now()).getSeconds();
        OrderSource orderSource = order.getOrderSource();
        if (SUI_XING_FU.equals(orderSource)) {
            if (seconds > 60 * 60) {
                throw new BusinessException(BusinessException.Type.DEFAULT, "订单过期已关闭");
            }
            payeeOrderParam.setExpireSeconds(60 * 60);
        } else {
            if (seconds > 60) {
                throw new BusinessException(BusinessException.Type.DEFAULT, "订单过期已关闭");
            }
            payeeOrderParam.setExpireSeconds(70);
        }

        payeeOrderParam.setStoreId(order.getStoreId());
        payeeOrderParam.setAmount(order.getPayPrice());
        payeeOrderParam.setAttach(order.getId() + "");
        payeeOrderParam.setMerchantId("1");
        payeeOrderParam.setNotifyUrl("");
        payeeOrderParam.setOutTradeNo(order.getOrderNo());

        payeeOrderParam.setProductName("星客多 (" + order.getStoreName() + ")");
        payeeOrderParam.setProductMessage(order.getServiceTypeName());

        ResponseUtils responseUtils = paymentRemoteService.toPay(payeeOrderParam);
        return responseUtils;
    }


    /**
     * 修改评价状态
     *
     * @param orderNo
     */
    public boolean edithadComment(String orderNo) {
        Order order = queryOrder(orderNo);
        order.setHadComment(true);
        orderMapper.updateById(order);

        return true;
    }

    /**
     * （小程序核对订单）
     *
     * @param orderNo
     * @param marketId
     * @param type
     */
    public void changeMarket(String orderNo, String marketId, String type) {
        if ("0".equals(marketId)) {
            marketId = null;
        }
        Order order = queryOrder(orderNo);
        String marketingId = order.getMarketingId();
        String activeId = order.getActivityId();
        String activityId = activeId;
        String marketingReceiveHistoryId = marketId;
        Integer preferentialType = 1;

        if ("0".equals(type)) {
            activityId = marketId;
            marketingReceiveHistoryId = marketingId;
            preferentialType = 0;
        }

        MarketActivityDto marketActivityDto = marketingRemoteService.getRecommendedPackage(activityId, marketingReceiveHistoryId, preferentialType, order, type);
        optimal(order, marketActivityDto, "0");
        log.info("changeMarket order:{}", order);
        orderMapper.updateById(order);
        updateOrderDetail(order);
    }


    /**
     * 更改预约时间(支付后
     *
     * @param orderAppointmentDto
     */
    public void editAppointmentCompleted(OrderAppointmentDto orderAppointmentDto) {
        Order order = orderService.queryOrderByOrderNO(orderAppointmentDto.getOrderNo());
        if (!OrderStatus.PAID.equals(order.getStatus())) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "订单状态已经改变");
        }
        if (order.getModifyOnce()) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "订单已更改过时间");
        }

        log.info("支付后过号重新预约orderAppointmentDto:{}", orderAppointmentDto);
        order.setAppointmentStartTime(DateTimeUtils.yyyy_MM_dd_H_m_s(orderAppointmentDto.getAppointmentStartTime()))
                .setAppointmentEndTime(DateTimeUtils.yyyy_MM_dd_H_m_s(orderAppointmentDto.getAppointmentEndTime()));

        boolean bf = marketingRemoteService.getStoreBypassFlowActivityDetail(order);
        log.info("支付后，修改预约时间:{}", bf);
        if (!bf) {
            throw new BusinessException(BusinessException.Type.DEFAULT, "活动或价格不一致");
        }

        //重新生成排队号
        String waitLineNo = waitLineRemoteService.getWaitLineNo(String.valueOf(order.getStoreId()), order.getAppointmentStartTime());
        if (StringUtils.isNotBlank(waitLineNo)) {
            order.setWaitingLineNo("A" + waitLineNo);
        }

        //TODO chi 库存
        /*inventoryRemoteService.unlockInventory(order);
        inventoryRemoteService.lockInventory(orderAppointmentDto.getAppointmentId(), StockStatusEnum.WAIT_FOR_SERVICE, order);*/
        boolean b = inventoryRemoteService.changeInventory(orderAppointmentDto.getAppointmentId(), StockStatusEnum.WAIT_FOR_SERVICE, order);
        if(!b){
            throw new BusinessException(BusinessException.Type.DEFAULT, "改约失败");
        }


        order.setAppointmentId(orderAppointmentDto.getAppointmentId());
        if (!order.getStatus().equals(OrderStatus.NOT_PAY)) {
            order.setModifyOnce(true);
        }

        OrderStatusLog orderStatusLog = order.addOrderAction(OrderAction.用户修改预约时间);

        int i = orderMapper.updateById(order);
        orderStatusLogMapper.insert(orderStatusLog);

        if (i > 0) {
            try {
                //预约变更提醒
                messagePushService.pushAppointmentChangeMessage(order);
//            服务进度提醒
                sendPush(order);
            } catch (Exception e) {
                log.error("发送通知失败:{}", e);
            }
        }

    }

    /**
     * 查询当前卡券id，有没有被使用
     *
     * @param userId
     * @param cardTickId
     * @return true 使用中
     * false 未使用
     */
    public boolean cardTick(String userId, String cardTickId, Integer marketingType) {
        String[] strings = adminRemoteService.queryUserIds(userId);
        List<Order> lists = orderMapper.selectList(new QueryWrapper<Order>().lambda().in(Order::getUserId, strings).eq(Order::getMarketingType, marketingType).eq(Order::getMarketingId, cardTickId).in(Order::getStatus, new OrderStatus[]{OrderStatus.IN_SERVICE, OrderStatus.PAID}));
        return !lists.isEmpty();
    }


    /**
     * 获取当天服务未开始的订单，自动过号
     *
     * @return
     */
    public void queryOverNumber() {
        List<Order> orders = orderMapper.selectList(new QueryWrapper<Order>().lambda().eq(Order::getStatus, OrderStatus.PAID));
        if (!orders.isEmpty()) {
            orders.forEach(order -> {
                try {
                    overNumber(String.valueOf(order.getId()), false);
                    log.info("{}, {} 每天24时未过号的订单过号", order.getId(), order.getOrderNo());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }


        List<Order> orders1 = orderMapper.selectList(new QueryWrapper<Order>().lambda().eq(Order::getStatus, OrderStatus.NOT_PAY));
        if (orders1 != null && orders1.size() > 0) {

            for (Order order : orders1) {
                if (order.getCreatedTime().plusSeconds(90L).compareTo(LocalDateTime.now()) < 0) {
                    try {
                        closeOrder(order.getId() + "");
                        log.info("{} 24时关闭待服务", order.getOrderNo());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        }


        List<Order> orders2 = orderMapper.selectList(new QueryWrapper<Order>().lambda().eq(Order::getStatus, OrderStatus.IN_SERVICE));
        log.info("{}每天24时服务中变成已完成", JSON.toJSONString(orders2));
        if (!orders2.isEmpty()) {
            orders2.forEach(order2 -> {
                try {
                    endService(String.valueOf(order2.getId()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }

    }


    /**
     * 服务进度提醒
     *
     * @param order
     */
    public void sendPush(Order order) {
        //获取当前时间
        LocalDateTime nowTime = LocalDateTime.now();
        //预约时间
        LocalDateTime appointmentStartTime = order.getAppointmentStartTime();
        //消息发送的时间
        LocalDateTime localDateTime = appointmentStartTime.minusMinutes(20);
        //距离
        long l = Duration.between(nowTime, localDateTime).toMillis();
        if (l > 0 && l < 2147483647) {
            taskService.addToDeplayQueue(new TaskModel(String.valueOf(order.getId()), TaskModelEnum.speed_progress, (int) l));
        }
    }


    /**
     * 服务进度提醒
     *
     * @param id
     */
    public void speedProgress(String id) {
        log.info("speedProgress id=" + id);
        Order order = orderService.getOrderById(id);
        //获取当前时间，就是消息发送时间
        LocalDateTime nowTime = LocalDateTime.now();
        //预约时间
        LocalDateTime appointmentStartTime = order.getAppointmentStartTime();
        //距离
        long l = Duration.between(nowTime, appointmentStartTime).toMinutes();
        //如果预约时间与发送时间间距在20分钟以内
        if (l > 0 && l <= 20 && OrderStatus.PAID == order.getStatus()) {
            messagePushService.pushServiceProgressMessage(order);
        }

    }

    /**
     * 发送优惠券和消息
     *
     * @param order
     */
    public void bindReceiveAccount(Order order) {
        try {
            log.info("bindReceiveAccount order:{}", JSON.toJSONString(order));
            ResponseUtils<ReceiveAccount> receiveAccountResponseUtils = marketingFeignService.bindCompensationReceiveAccount(order.getUserId());
            log.info("bindReceiveAccount receiveAccountResponseUtils:{}", JSON.toJSONString(receiveAccountResponseUtils));
            if (receiveAccountResponseUtils.success()) {
                ReceiveAccount data = receiveAccountResponseUtils.getData();
                messagePushService.pushOrderIndemnityMessage(order, data.getMarketingName(), DateTimeUtils.yyyy_MM_dd(DateTimeUtils.yyyy_MM_dd_HH_mm_ss(data.getUseStartTime())) + "-" + DateTimeUtils.yyyy_MM_dd(DateTimeUtils.yyyy_MM_dd_HH_mm_ss(data.getUseEndTime())));
            }
        } catch (Exception e) {
            log.info("bindReceiveAccount 发送优惠券和消息异常:{}", JSON.toJSONString(e));

        }

    }




    /**
    * @description: Barber下单发送优惠券
    * @author: ch
    * @Param [order]
    * @return void
    * @date: 2019-07-12 17:06
    **/
    public void bindBarberReceiveAccount(Order order) {
        try {
            if("7".equals(order.getServiceTypeId()) || "4".equals(order.getServiceTypeId())|| "6".equals(order.getServiceTypeId())){
                log.info("Barber下单发送优惠券 order:{}", JSON.toJSONString(order));
                ResponseUtils<ReceiveAccount> receiveAccountResponseUtils = marketingFeignService.bindBarberReceiveAccount(Long.valueOf(order.getUserId()),order.getServiceTypeId());
                log.info("Barber下单发送优惠券 receiveAccountResponseUtils:{}", JSON.toJSONString(receiveAccountResponseUtils));
            }
        } catch (Exception e) {
            log.info("Barber下单发送优惠券异常:{}", JSON.toJSONString(e));

        }

    }


    public String refundApply(String storeId) {
        Integer integer = orderMapper.selectCount(new QueryWrapper<Order>().lambda().eq(Order::getStoreId, storeId).eq(Order::getStatus, OrderStatus.REFUND_APPLY));
        if (integer > 0) {
            return integer + "待审核";
        }
        return "";
    }


    /**
     * 更新订单详情
     *
     * @param order
     */
    public void updateOrderDetail(Order order) {
        OrderDetail orderDetail = orderDetailMapper.selectOne(new QueryWrapper<OrderDetail>().lambda().eq(OrderDetail::getOrderNo, order.getOrderNo()).last("LIMIT 1"));
        if (orderDetail != null) {
            orderDetail.setActivityDetail(order.getActivityDetail());
            orderDetail.setCardCouponDetail(order.getCardCouponDetail());
            orderDetailMapper.updateById(orderDetail);
        }

    }


    /**
     * 补全活动和卡券信息
     *
     * @param order
     */
    public void queryOrderDetail(Order order) {
        if (order != null) {
            OrderDetail orderDetail = orderDetailMapper.selectOne(new QueryWrapper<OrderDetail>().lambda().eq(OrderDetail::getOrderNo, order.getOrderNo()).last("LIMIT 1"));
            if (orderDetail != null) {
                order.setActivityDetail(orderDetail.getActivityDetail());
                order.setCardCouponDetail(orderDetail.getCardCouponDetail());
            }
        }
    }


    /**
     * @return void
     * @description: 补全卡券信息List<Order>
     * @author: ch
     * @Param [orders]
     * @date: 2019-06-18 15:27
     **/
    public void queryOrdersDetail(List<Order> orders) {
        if (orders.isEmpty()) {
            return;
        }
        String[] orderNos = orders.stream().map(Order::getOrderNo).toArray(String[]::new);
        List<OrderDetail> orderDetails = orderDetailMapper.selectList(new QueryWrapper<OrderDetail>().lambda().in(OrderDetail::getOrderNo, orderNos));
        if (!orderDetails.isEmpty()) {
            Map<String, OrderDetail> map = orderDetails.stream().collect(Collectors.toMap(OrderDetail::getOrderNo, Function.identity()));
            orders.forEach(order -> ordersDetail(order, map));
        }
    }

    /**
     * @return void
     * @description: 补全卡券信息 店铺信息
     * @author: ch
     * @Param [order, map]
     * @date: 2019-06-18 16:31
     **/
    public void ordersDetail(Order order, Map<String, OrderDetail> map) {
        String orderNo = order.getOrderNo();
        if (map.containsKey(orderNo)) {
            OrderDetail orderDetail = map.get(orderNo);
            order.setActivityDetail(orderDetail.getActivityDetail());
            order.setCardCouponDetail(orderDetail.getCardCouponDetail());
        }
        orderService.complementInfo(order);
    }


    /**
     * @return void
     * @description: 90天内，除快剪学院id，测试用户id外，同一用户id如有2条未服务完成的订单，不能够继续下单，提示：
     * 需结束至少1未服务订单，才能下单
     * @author: ch
     * @Param [orderInitDto]
     * @date: 2019-06-19 15:11
     **/
    public void serviceNotRendered(OrderInitDto orderInitDto) {
        if (!"7".equals(orderInitDto.getStoreId()) && !"112".equals(orderInitDto.getStoreId())) {
            // 获取账号合并ids
            String[] strings = adminRemoteService.queryUserIds(orderInitDto.getUserId());
            Integer integer = orderMapper.selectCount(new QueryWrapper<Order>().lambda().in(Order::getUserId, strings).eq(Order::getStatus, OrderStatus.PAID).apply(" DATE_SUB(CURDATE(), INTERVAL 90 DAY) <= date(created_time)"));
            if (integer >= 2) {
                throw new BusinessException(BusinessException.Type.DEFAULT, "您还有未服务的订单");
            }
        }
    }


    /**
     * @return void
     * @description: 同一用户id，使用同一免费卡id，如有1条未服务完成的订单，不能够继续下单，提示：
     * 需结束后继续下单
     * @author: ch
     * @Param [marketActivityDto]
     * @date: 2019-06-19 15:42
     **/
    public void freeCardUse(MarketActivityDto marketActivityDto, Order order) {
        log.info("免费卡风控marketActivityDto{}", JSON.toJSONString(marketActivityDto));
        if (marketActivityDto != null && marketActivityDto.getMarketingType() != null && marketActivityDto.getMarketingType() == 2 && marketActivityDto.getMarketingDiscountType() == 3) {
            String[] strings = adminRemoteService.queryUserIds(order.getUserId());
            Integer integer = orderMapper.selectCount(new QueryWrapper<Order>().lambda().in(Order::getUserId, strings).in(Order::getStatus, new OrderStatus[]{OrderStatus.IN_SERVICE, OrderStatus.PAID}).notIn(Order::getOrderNo, order.getOrderNo()).eq(Order::getMarketingType, "2").eq(Order::getMarketingId, marketActivityDto.getMarketingId()));
            log.info("免费卡风控integer{}", integer);

            if (integer >= 1) {
                throw new BusinessException(BusinessException.Type.DEFAULT, "您有未完成服务的订单");
            }
        }

    }



    /**
     *
     * @Title: getPlatformSubsidyAmount
     * @Description: 获取公司补贴金额
     * @param @param  originPrice 订单原价
     * @param @param  currentPrice 订单实际价格(订单现价)支付价格
     * @param @param  reducePrice 减免价格  卡券优惠价格
     * @param @param  subsidyType 补贴方式  补贴方式
     * @param @param  subsidyBasicAmount 补贴基础金额  补贴金额
     * @param @return 设定文件
     * @return BigDecimal 返回类型
     * @throws @author lixin
     * @date Jul 16, 2019 3:08:14 PM
     */
    public BigDecimal getPlatformSubsidyAmount(BigDecimal originPrice, BigDecimal currentPrice, BigDecimal reducePrice,
                                               Integer subsidyType, BigDecimal subsidyBasicAmount) {
        log.info("getPlatformSubsidyAmount originPrice={},currentPrice={},reducePrice={},subsidyType={},subsidyBasicAmount={}", originPrice,currentPrice,reducePrice,subsidyType,subsidyBasicAmount);
        // 返回的公司承担金额
        BigDecimal returnPrice = BigDecimal.valueOf(0);
        // 按公司承担的比列承担
        if (subsidyType == 0) {
            // 补贴金额=减免价格*公司承担的比例
//            returnPrice = reducePrice.multiply(subsidyBasicAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
            returnPrice = reducePrice.multiply(subsidyBasicAmount).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_UP);
        }
        // 按固定结算金额承担
        if (subsidyType == 1) {
            // 补贴金额=min(结算金额，订单原价)-订单实际价格。
            BigDecimal minPrice = originPrice.compareTo(subsidyBasicAmount) < 0 ? originPrice : subsidyBasicAmount;
            returnPrice = currentPrice.compareTo(minPrice) > 0 ? BigDecimal.valueOf(0)
                    : minPrice.subtract(currentPrice);
        }
        // 按固定补贴金额承担
        if (subsidyType == 2) {
            // 补贴金额=固定补贴金额
            returnPrice = subsidyBasicAmount;
        }
        return returnPrice;
    }





    /**
    * @description: 制作手工单
    * @author: ch
    * @Param [orderManualSingle]
    * @return void
    * @date: 2019-08-05 12:06
    **/
    public void editManualSingle(OrderManualSingle orderManualSingle) {
        Order order = orderService.queryOrderByOrderNO(orderManualSingle.getOrderNo());
        OrderStatus status = order.getStatus();
        if(OrderStatus.PAID.equals(status) || OrderStatus.IN_SERVICE.equals(status) || OrderStatus.OVER_NUMBER.equals(status) || OrderStatus.EVALUATION_DONE.equals(status) || OrderStatus.REFUND_REGECT.equals(status) || OrderStatus.REFUND_APPLY.equals(status)){
            manualSingle(orderManualSingle,order);

        }else if(OrderStatus.REFUND_DONE.equals(status) && order.getServiceDown()){
            manualSingle(orderManualSingle,order);

        } else {
            throw new BusinessException(BusinessException.Type.DEFAULT, "订单状态已经改变");
        }
    }


    public void manualSingle(OrderManualSingle orderManualSingle,Order order){
        OrderStatus status = order.getStatus();
        order.setAdminId(orderManualSingle.getAdminId()).setAdminName(orderManualSingle.getAdminName())
                .setServeStartTime(DateTimeUtils.yyyy_MM_dd_HH_mm_ss(orderManualSingle.getServeStartTime()))
                .setServeEndTime(DateTimeUtils.yyyy_MM_dd_HH_mm_ss(orderManualSingle.getServeEndTime()));

        OrderStatusLog orderStatusLog = null;
        if(OrderStatus.PAID.equals(status) || OrderStatus.IN_SERVICE.equals(status) || OrderStatus.OVER_NUMBER.equals(status)){
            orderStatusLog = order.covertStatus(OrderStatus.EVALUATION_DONE, OrderAction.生成手工单);
            inventoryRemoteService.updateInventory(StockStatusEnum.ALREADY, order);
        } else {
            orderStatusLog = order.addOrderAction(OrderAction.生成手工单);
        }

        order.setServiceDown(true);

        StringBuffer sb = new StringBuffer();
        sb.append(order.getStatus().getValue()+"_");
        sb.append(orderManualSingle.getServeStartTime()+"-");
        sb.append(orderManualSingle.getServeEndTime());
        orderStatusLog.setRemark(sb.toString());

        orderMapper.updateById(order);
        orderStatusLogMapper.insert(orderStatusLog);
    }



    /**
     * 清洗数据
     * @param start
     * @param end
     */
    public void flush(Long start, Long end) {
        List<Order> orders1 = orderMapper.selectList(new QueryWrapper<Order>().lambda()
                .gt(Order::getId, start)
                .lt(Order::getId, end)
                .eq(Order::getPaySuccess, true)
                .gt(Order::getPayPrice, BigDecimal.ZERO)
            );


        List<String> collect = orders1.stream().map(Order::getOrderNo).collect(Collectors.toList());
        log.info("{}",JSON.toJSONString(collect));

        for (Order order : orders1) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            try {
                ResponseUtils<PayeeOrderResponseDto> query = paymentFeignService.query("1", order.getOrderNo());
                if(query.success()){
                    String tradeNo = query.getData().getTradeNo();

                    if(PayType.ALIPAY.equals(order.getPayType())){
                        order.setAlipayTradeNo(tradeNo);
                    }else {
                        order.setOutOrderNo(tradeNo);
                    }
                    log.info("no:{}", order.getOrderNo());
                    orderMapper.updateById(order);
                }
            } catch (Exception e) {
                log.error("{}", e);
            }


        }

    }


    public void consumeMessage() {
        executorService.execute(this::queryOverNumber);
    }
}



























